package cn.liyunqi.findimg.task;

import cn.liyunqi.findimg.localdb.Constants;
import cn.liyunqi.findimg.utils.FindImgUtil;
import org.apache.commons.text.StringEscapeUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

import java.io.*;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.UnaryOperator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class BaiduTask extends ProgressBarViewTask {

    private static final int FOLDER_LIMIT = 30;

    class ImgTask implements Callable<Integer>{
        private String searchWord;
        private String imgPath;
        private int index;
        private Map<String , AtomicInteger> searchMap;

        public ImgTask(int index,String imgPath,String searchWord, Map<String, AtomicInteger> searchMap){
            this.index = index;
            this.searchWord = searchWord;
            this.searchMap = searchMap;
            this.imgPath = imgPath;
        }

        @Override
        public Integer call() throws Exception {


            int imgCount = 0;
            //如果连续8张都是不合格的图片那么不在往下查找了
            int continuityFail = 0;

            while (imgCount <= FOLDER_LIMIT && continuityFail <= 8){
                //获取当前检索页码
                int page = searchMap.get(searchWord).getAndAdd(1);

                String keyword = null;

                try {
                    keyword = java.net.URLEncoder.encode(searchWord, "UTF-8");

                    String url ="http://image.baidu.com/search/avatarjson?tn=resultjsonavatarnew&ie=utf-8&word="+keyword+"&cg=star&pn="+page*30+"&rn=30&itg=0&z=0&fr=&width=&height=&lm=-1&ic=0&s=0&st=-1&gsm="+Integer.toHexString(page*30);

                    FindImgUtil.sop(url);

                    Document document = Jsoup.connect(url).data("query", "Java")//请求参数
                            .userAgent("Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)")//设置urer-agent  get();
                            .timeout(5000)
                            .get();
                    String xmlSource = document.toString();
                    xmlSource = StringEscapeUtils.unescapeHtml3(xmlSource);
                    FindImgUtil.sop(xmlSource);

                    String reg = "objURL\":\"http://.+?\\.jpg";
                    Pattern pattern = Pattern.compile(reg);
                    Matcher m = pattern.matcher(xmlSource);

                    //获取到所有的图片地址 将其派到需要前往的线程池获取图片

                    while (m.find()) {

                        String localPath = imgPath + "/F" + FindImgUtil.formatNumToStr(index + 1) + "_" + searchWord + "_" + FindImgUtil.formatNumToStr(page * 30 + (imgCount + 1)) + ".jpg";
                        String finalURL = m.group().substring(9);

                        FindImgUtil.sop(searchWord + ":"+finalURL);

                        int reslut = FindImgUtil.downloadEligibleImg(finalURL,localPath);

                        if(reslut > 0){
                            //成功的话需要 计数追加 连续失败清空 追加进度
                            imgCount++;
                            continuityFail = 0;


                            if(imgCount >= FOLDER_LIMIT){
                                //当超出限度的情况下不追加进度
                                updateMsg("【"+ searchWord + "】寻找成功。。。第" + imgCount +"张图");
                            }else{
                                updateProgress("【"+ searchWord + "】寻找成功。。。第" + imgCount +"张图" , currentSpeed.updateAndGet(new UnaryOperator<Double>() {
                                    @Override
                                    public Double apply(Double aDouble) {
                                        return aDouble + 1.0;
                                    }
                                }),max);
                            }

                            //updateProgress(searchWord + "。。。第" + imgCount + "张成功",,);
                        }else{
                            continuityFail++;
                        }

                    }

                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }

            return imgCount;
        }
    }



    private List<String> searchWordList;

    List<Future> futureList = new ArrayList();

    private ExecutorService executor;
    private CompletionService<Integer> completionService;

    private String selectExportPath;

    private AtomicReference<Double> currentSpeed = null;
    private double max = 0;

    public BaiduTask(List<String> searchWordList ,String selectExportPath){

        this.searchWordList = searchWordList;
        this.selectExportPath = selectExportPath;

    }

    @Override
    protected void doTask() throws Exception{


        // 该进程 0.5 9 0.5 开
        /**
         * 第一步 前置 任务
         *  检查文件夹 判断需要查询的页数 获取起始查询的页数
         *
         * 第二步 抓取高质量的图片
         *
         * 第三步 将已经查询的最终页数回写到每个文件夹下的一个文件中 形成闭环
         *
         * 第四步 询问是否需要加入导入到对应文件夹
         */
        // 首先 计算所有需要查询的 图片总数量
        if(searchWordList.size() > 0){
            //预计查询30张高质量的图片
            int totalImg = searchWordList.size() * FOLDER_LIMIT;

            //更具需要查询的图片计算得 前置需要准备的任务 以及总进度
            max = totalImg / 90.0 * 100.0;

            double oneFive = max/20.0;

            Map<String , AtomicInteger> searchMap = new LinkedHashMap<>();

            Map<String , String> searchPathMap = new LinkedHashMap<>();

            //初始化存放文件夹
            File dataFile = new File(selectExportPath);
            try {
                if(!dataFile.exists()){
                    dataFile.mkdir();
                }
                updateProgress("正在初始化文件夹。。。",0,max);

                //获取每个检索条目的以及检索起始页
                for (int i = 0; i < searchWordList.size(); i++) {
                    String searchWord = searchWordList.get(i);
                    //创建文件夹

                    String imgPath = searchPathMap.get(searchWord);
                    if(imgPath == null){
                        imgPath = selectExportPath + File.separator + "FI_" + searchWord;
                        searchPathMap.put(searchWord,imgPath);
                    }


                    File imgFolder = new File(imgPath);
                    if(!imgFolder.exists()){
                        imgFolder.mkdir();
                    }

                    String imgPagePath = imgPath + File.separator + "page.ini";

                    AtomicInteger page = new AtomicInteger(0);

                    FileReader  imgPageFr = null;
                    BufferedReader  imgPageBr = null;

                    try {
                        File imgPageFile = new File(imgPagePath);
                        if(imgPageFile.exists()){
                            imgPageFr = new FileReader(imgPageFile);
                            imgPageBr = new BufferedReader(imgPageFr);
                            String strPage = imgPageBr.readLine();

                            if(strPage != null && !strPage.trim().isEmpty()){
                                page = new AtomicInteger(Integer.valueOf(strPage));
                            }
                        }
                    }catch (Exception ex){
                        System.err.println("读取文件夹下的配置出错 。。。 " + searchWord);
                        ex.printStackTrace();
                    }finally {
                        try {
                            if(imgPageBr != null){
                                imgPageBr.close();
                            }
                        }catch (Exception ex){
                            ex.printStackTrace();
                        }
                        try {
                            if(imgPageFr != null){
                                imgPageFr.close();
                            }
                        }catch (Exception ex){
                            ex.printStackTrace();
                        }


                    }

                    //确认每张图片查询的页码
                    searchMap.put(searchWord,page);

                    updateProgress("正在分配存储空间。。。" + searchWord,oneFive / searchWordList.size() * (i + 1),max);
                }

                updateProgress("存储空间分配完成。。。",oneFive,max);
                currentSpeed = new AtomicReference<>();
                currentSpeed.set(oneFive);

                //第二步 开启多个线程 抓取高质量的图片

                //创建线程池执行每一个任务 这个线程池用来获取
                int numThread = 7;
                executor = Executors.newFixedThreadPool(numThread);
                completionService = new ExecutorCompletionService<Integer>(executor);



                for (int i = 0; i < searchWordList.size(); i++) {

                    String searchWord = searchWordList.get(i);

                    //将该任务放入线程中
                    Future<Integer> future = completionService.submit(new ImgTask(i,searchPathMap.get(searchWord),searchWord,searchMap));
                    //记录每个任务的返回值 用于销毁任务
                    futureList.add(future);
                }
                for(int i = 0;i<searchWordList.size();i++ ){
                    Integer future = completionService.take().get();
                }

                executor.shutdownNow();
                executor = null;
                completionService = null;

                //所有任务完成后 进度刷新
                updateProgress("爬取作业完成。。。",oneFive + totalImg,max);
                //将当前页的页码写入文件夹中
                int searchMapIndex = 0;
                int searchMapSize = searchMap.size();
                for (Map.Entry<String, AtomicInteger> entry : searchMap.entrySet()) {

                    String key = entry.getKey();
                    AtomicInteger value = entry.getValue();

                    //创建文件夹

                    String imgPagePath = searchPathMap.get(key) + File.separator + "page.ini";

                    File imgPageFile = new File(imgPagePath);

                    FileWriter imgPageFw = null;
                    BufferedWriter imgPageBw = null;
                    try {

                        imgPageFw = new FileWriter(imgPageFile);
                        imgPageBw = new BufferedWriter(imgPageFw);

                        imgPageBw.write(value.toString());

                        updateProgress("正在保存当前页码。。。" + key,oneFive + totalImg + oneFive/searchMapSize * (searchMapIndex + 1),max);

                        searchMapIndex = searchMapIndex + 1;

                    } catch (Exception e) {
                        e.printStackTrace();
                    }finally {
                        try {
                            if(imgPageBw != null){
                                imgPageBw.close();
                            }
                        }catch (Exception ex){
                            ex.printStackTrace();
                        }
                        try {
                            if(imgPageFw != null){
                                imgPageFw.close();
                            }
                        }catch (Exception ex){
                            ex.printStackTrace();
                        }
                    }
                }

                updateProgress("作业完成。。。[]~(￣▽￣)~*",max,max);

            }catch (Exception ex){
                throw ex;
            }

        }

    }


    @Override
    public void closeHandler() {

        //异常关闭时需要先将所有任务暂停  先是查询任务 然后寻图任务 //然后写入文件
        for (int i = 0; i < futureList.size(); i++) {
            try {
                futureList.get(i).cancel(true);
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
        if(executor != null){
            executor.shutdownNow();
            executor = null;
            completionService = null;
        }

        this.cancel();
    }
}
